/*
* Copyright 2017, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
*		Adrien Destugues <pulkomandy@pulkomandy.tk>
*/
#include "Lpstyl.h"


LpstylDriver::LpstylDriver(BMessage* message, PrinterData* printerData,
	const PrinterCap* printerCap)
	: GraphicsDriver(message, printerData, printerCap)
{
}


bool
LpstylDriver::StartDocument()
{
	_EjectAndReset();
	_IdentifyPrinter();
	_ColorCartridge();
	return true;
}


bool
LpstylDriver::StartPage()
{
	if (fPrinterType < kStyleWriter2400)
		WriteSpoolData("nuA", 3);
	else
		WriteSpoolChar('L');
	return true;
}


bool
LpstylDriver::NextBand(BBitmap* bitmap, BPoint* offset)
{
	fprintf(stderr, "Next band at %f %f\n", offset->x, offset->y);

	int page_height = GetPageHeight();

	// Advance the cursor
	offset->y += bitmap->Bounds().Height();

	// Have we reached the end of the page yet?
	if (offset->y >= page_height)
	{
		offset->y = -1;
		offset->x = -1;
	}

	return true;
}


bool
LpstylDriver::EndPage(int page)
{
	fprintf(stderr, "end page %d\n", page);
	return true;
}


bool
LpstylDriver::EndDocument(bool success)
{
	return true;
}


/** Eject the current page (if any) and reset the printer.
 */
void
LpstylDriver::_EjectAndReset(void)
{
	_WriteFFFx('I');

	int s1;

	do {
		for (;;) {
			try {
				s1 = _GetStatus('1');
				break;
			} catch(const TransportException&) {
				continue;
			}
		}

		if (s1 == 1) {
			// Check for stylewriter1, where status 1 doesn't g to 0 on init.
			if (_GetStatus('2') == 0 && _GetStatus('B') == 0xa0)
				break;
		}
	} while (s1 == 1);
}


void
LpstylDriver::_IdentifyPrinter(void)
{
	WriteSpoolChar('?');

	char smallBuf[32];
	int i = 0;
	for (i = 0; i < 31; i++) {
		smallBuf[i] = ReadSpoolChar();
		if (smallBuf[i] == 0x0D)
			break;
	}
	smallBuf[i] = 0;

	if (strcmp(smallBuf, "IJ10\x0D") == 0)
		fPrinterType = kStyleWriter;
	else if (strcmp(smallBuf, "SW\x0D") == 0)
		fPrinterType = kStyleWriter2;
	else if (strcmp(smallBuf, "SW3\x0D") == 0)
		fPrinterType = kStyleWriter3;
	else if (strcmp(smallBuf, "CS\x0D") == 0) {
		switch (_GetStatus('p'))
		{
			default:
			case 1:
				fPrinterType = kStyleWriter2400;
				break;
			case 2:
				fPrinterType = kStyleWriter2200;
				break;
			case 4:
				fPrinterType = kStyleWriter1500;
				break;
			case 5:
				fPrinterType = kStyleWriter2500;
				break;
		}
	}
}


bool
LpstylDriver::_ColorCartridge()
{
	WriteSpoolChar('D');
	unsigned char i = _GetStatus('H');
	return i & 0x80;
}


/** Send a 4-byte command to the printer.
 *
 * These commands can be sent at any time, because their prefix is FFFFFF, a
 * sequence which can't be generated by the data compression algorithm
 */
void
LpstylDriver::_WriteFFFx(char x)
{
	unsigned char str[4];
	str[0] = str[1] = str[2] = 0xFF;
	str[3] = x;
	WriteSpoolData(str, 4);
}


/** Get one of the printer status bytes.
 *
 * There are 3 status registers, 1, 2, and B. Each returns some different
 * information about the printer state.
 */
int
LpstylDriver::_GetStatus(char reg)
{
	_WriteFFFx(reg);
	return ReadSpoolChar();
}
